<!DOCTYPE html>
<html>
<head>
<style>
body {
    height: 2000px;
}

.positionFixed {
    position: fixed;
}

.positionAbsolute {
    position: absolute;
}

.overflow {
    width: 100px;
    height: 100px;
    border: 2px solid black;
    overflow: scroll;
}

.scrolled {
    background-color: blue;
    width: 75px;
    height: 24px;
    margin: 4px;
    position: relative;
}

.onTop {
    z-index: 2;
}

pre {
    position: absolute;
    top: 400px;
    z-index: -1;
}

.positioned {
    background-color: purple;
    width: 80px;
    height: 40px;
    top: 65px;
    left: 25px;
}

.sibling {
    background-color: green;
    width: 50px;
    height: 100px;
    top: 10px;
    left: 5px;
    z-index: 1;
}
</style>
<script>
if (window.internals)
    internals.settings.setPreferCompositingToLCDTextEnabled(true);

function addDomElement(elementType, className, id, parent, description, indent)
{
    var element = document.createElement(elementType);
    element.setAttribute("class", className);
    element.setAttribute("id", id);
    if (parent === "body")
        document.body.appendChild(element);
    else
        document.getElementById(parent).appendChild(element);

    if (elementType === "div") {
        for (var i = 0; i < indent; ++i)
            description.push("  ");
        description.push("+ ");
        description.push(id);
        if (className) {
            description.push(", class: ");
            description.push(className);
        }
        description.push("\n");
    }

    return element;
}

function positionElement(id, left, top) {
    var element = document.getElementById(id);
    element.style.left = left + "px"; 
    element.style.top = top + "px";
}

function buildDom(description, indent, parameters)
{
    var configurationElement = parameters.title;
    var containerElement = "container-" + parameters.title;
    var ancestorElement = "ancestor-" + parameters.title;
    var parentElement = configurationElement;

    addDomElement("div", "positionAbsolute", configurationElement, "body", description, indent);
    positionElement(configurationElement, parameters.left, parameters.top);
    if (parameters.hasSibling) {
        addDomElement("div", "", ancestorElement, parentElement, description, indent);
        indent++;
        var siblingElement = "sibling-" + parameters.title;
        addDomElement("div", "positionFixed sibling", siblingElement, ancestorElement, description, indent);
        positionElement(siblingElement, parameters.left + 5, parameters.top + 10);
        parentElement = ancestorElement;
    }

    var overflowClass = parameters.isContainingBlock
        ? "positionAbsolute overflow"
        : "overflow";

    addDomElement("div", overflowClass, containerElement, parentElement, description, indent);
    indent++;

    parentElement = containerElement;
    if (parameters.hasGrandchildren) {
        var scrollingContainerElement = "scrollingContainer-" + parameters.title;
        addDomElement("div", "", scrollingContainerElement, parentElement, description, indent);
        indent++;
        parentElement = scrollingContainerElement;
    }

    var positionedClass = parameters.isFixedPositioned
        ? "positionFixed"
        : "positionAbsolute";

    var positionedElement = "positioned-" + parameters.title;
    addDomElement("div", positionedClass + " positioned", positionedElement, parentElement, description, indent);
    if (parameters.isFixedPositioned)
        positionElement(positionedElement, parameters.left + 25, parameters.top + 65);

    for (var i = 0; i < 5; ++i) {
        var scrolledClass = "scrolled";
        if ((i % 2) == 0)
            scrolledClass += " onTop";
        addDomElement("div", scrolledClass, "scrolled-" + parameters.title, parentElement, description, indent);
    }
}

function testConfiguration(configuration, index, description) {
    description.push("\n" + (index + 1) + ". '" + configuration.title + "'\n");
    var configurationsPerRow = 4;
    configuration.top = 10 + 120 * (Math.floor(index / configurationsPerRow));
    configuration.left = 10 + 120 * (index % configurationsPerRow);
    buildDom(description, 0, configuration);
}

function doTest() {
    if (window.internals)
        testRunner.dumpAsTextWithPixelResults();

        // Some configurations are as not meaningful for fixed-pos. For example, we
        // alternate between having the scroll container be a containing block for
        // the positioned descendant. For the fixed-pos case, the containing block
        // will be the viewport.
    var configurations = [
        { 
            'title': 'absolute-grandchildren-not-contained',
            'isFixedPositioned': false,
            'isContainingBlock': false,
            'hasSibling': false,
            'hasGrandchildren': true,
        },
        {
            'title': 'absolute-grandchildren',
            'isFixedPositioned': false,
            'isContainingBlock': true,
            'hasSibling': false,
            'hasGrandchildren': true,
        },
        {
            'title': 'absolute-not-contained',
            'isFixedPositioned': false,
            'isContainingBlock': false,
            'hasSibling': false,
            'hasGrandchildren': false,
        },
        {
            'title': 'absolute-sibling-grandchildren-not-contained',
            'isFixedPositioned': false,
            'isContainingBlock': false,
            'hasSibling': true,
            'hasGrandchildren': true,
        },
        {
            'title': 'absolute-sibling-grandchildren',
            'isFixedPositioned': false,
            'isContainingBlock': true,
            'hasSibling': true,
            'hasGrandchildren': true,
        },
        {
            'title': 'absolute-sibling-not-contained',
            'isFixedPositioned': false,
            'isContainingBlock': false,
            'hasSibling': true,
            'hasGrandchildren': false,
        },
        {
            'title': 'absolute-sibling',
            'isFixedPositioned': false,
            'isContainingBlock': true,
            'hasSibling': true,
            'hasGrandchildren': false,
        },
        {
            'title': 'absolute',
            'isFixedPositioned': false,
            'isContainingBlock': true,
            'hasSibling': false,
            'hasGrandchildren': false,
        },
        {
            'title': 'fixed-sibling-grandchildren',
            'isFixedPositioned': true,
            'isContainingBlock': true,
            'hasSibling': true,
            'hasGrandchildren': true,
        },
        {
            'title': 'fixed-sibling',
            'isFixedPositioned': true,
            'isContainingBlock': true,
            'hasSibling': true,
            'hasGrandchildren': false,
        },
        {
            'title': 'fixed-grandchildren',
            'isFixedPositioned': true,
            'isContainingBlock': true,
            'hasSibling': false,
            'hasGrandchildren': true,
        },
        {
            'title': 'fixed',
            'isFixedPositioned': true,
            'isContainingBlock': true,
            'hasSibling': false,
            'hasGrandchildren': false,
        },
    ];

    var description = [ "We check that scrolling is accelerated in the following configurations:\n" ];
    for (var i = 0; i < configurations.length; ++i)
        testConfiguration(configurations[i], i, description);

    var containers = document.getElementsByClassName("overflow");
    for (var i = 0; i < containers.length; ++i) { 
      var container = containers[i];
      container.scrollTop = container.scrollHeight - container.clientHeight;
    }

    addDomElement("pre", "", "console", "body", [], 0);
    var pre = document.getElementById("console");

    if (window.internals) {
        var layerTreeAsText = internals.layerTreeAsText(document);
        pre.style.left = "-80000px";
        pre.innerHTML = layerTreeAsText;
    } else {
        pre.innerHTML = description.join("");
    }
}

window.onload = doTest;

</script>
</head>
<body>
</body>
</html>
